home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / gnu / gnpltsrc.lha / binary.c < prev    next >
C/C++ Source or Header  |  1996-01-22  |  12KB  |  424 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: binary.c,v 1.6 1994/09/13 16:11:18 alex Exp $";
  3. #endif
  4.  
  5. /*
  6.  * The addition of gnubin and binary, along with a small patch
  7.  * to command.c, will permit gnuplot to plot binary files.
  8.  * gnubin  - contains the code that relies on gnuplot include files
  9.  *                     and other definitions
  10.  * binary      - contains those things that are independent of those 
  11.  *                     definitions and files
  12.  *
  13.  * With these routines, hidden line removal of your binary data is possible!
  14.  *
  15.  * Last update:  3/29/92 memory allocation bugs fixed. jvdwoude@hut.nl
  16.  *               3/09/92 spelling errors, general cleanup, use alloc with no
  17.  *                       nasty fatal errors
  18.  *               3/03/92 for Gnuplot 3.24.
  19.  * Created from code for written by RKC for gnuplot 2.0b.
  20.  *
  21.  * Copyright (c) 1991,1992 Robert K. Cunningham, MIT Lincoln Laboratory
  22.  *
  23.  */
  24.  
  25. #include <math.h>
  26.  
  27.  
  28. #include "plot.h"   /* We have to get TRUE and FALSE */
  29. #include "stdfn.h"
  30. #include "binary.h"
  31.  
  32. /* 
  33.  * This routine scans the first block of the file to see if the file is a 
  34.  * binary file.  A file is considered binary if 10% of the characters in it 
  35.  * are not in the ascii character set. (values < 128), or if a NUL is found.
  36.  * I hope this doesn't break when used on the bizzare PC's.
  37.  */
  38. int
  39.   is_binary_file(fp)
  40. register FILE *fp;
  41. {
  42.   register int i,len;
  43.   register int odd;                /* Contains a count of the odd characters */
  44.   long where;
  45.   register unsigned char *c;
  46.   unsigned char buffer[512];
  47.  
  48.   if((where = ftell(fp)) == -1){ /* Find out where we start */
  49.     fprintf(stderr,"Notice: Assuming unseekable data is not binary\n");
  50.     return(FALSE);
  51.   }
  52.   else {
  53.     rewind(fp);
  54.  
  55.     len = fread(buffer,sizeof(char),512,fp);
  56.     if (len <= 0)                      /* Empty file is declared ascii */
  57.       return(FALSE);
  58.  
  59.     c = buffer;
  60.  
  61.     /* now scan buffer to look for odd characters */
  62.     odd = 0;
  63.     for (i=0; i<len; i++,c++) {
  64.       if (!*c) {              /* NUL _never_ allowed in text */
  65.     odd += len;
  66.     break;
  67.       }
  68.       else if ((*c & 128) ||/* Meta-characters--we hope it's not formatting */
  69.            (*c == 127)|| /* DEL */
  70.            (*c < 32 && 
  71.         *c != '\n' && *c != '\r' && *c != '\b' &&
  72.         *c != '\t' && *c != '\f' && *c != 27 /*ESC*/))
  73.     odd++;
  74.     }
  75.   
  76.     fseek(fp,where,0); /* Go back to where we started */
  77.  
  78.     if (odd * 10 > len)             /* allow 10% of the characters to be odd */
  79.       return(TRUE);
  80.     else
  81.       return(FALSE);
  82.   }
  83. }
  84. /*========================= I/O Routines ================================
  85.   These may be useful for situations other than just gnuplot.  Note that I 
  86.   have included the reading _and_ the writing routines, so others can create 
  87.   the file as well as read the file.
  88. */
  89.  
  90. /*
  91.   This function reads a matrix from a stream
  92.  
  93.   This routine never returns anything other than vectors and arrays
  94.   that range from 0 to some number.  
  95.  
  96. */
  97. #define START_ROWS 100/* Each of these must be at least 1 */
  98. #define ADD_ROWS 50
  99. int
  100.   fread_matrix(fin,ret_matrix,nr,nc,row_title,column_title)
  101. FILE *fin;
  102. float GPFAR * GPFAR * GPFAR *ret_matrix,GPFAR * GPFAR * row_title, GPFAR * GPFAR *column_title;
  103. int *nr,*nc;
  104. {
  105.   float  GPFAR * GPFAR *m, GPFAR *rt, GPFAR *ct;
  106.   register int num_rows = START_ROWS;
  107.   register int num_cols;
  108.   register int current_row = 0;
  109.   register float  GPFAR * GPFAR *temp_array;
  110.   float fdummy;
  111.   
  112.   fread(&fdummy,sizeof(fdummy),1,fin);
  113.   num_cols = (int)fdummy;
  114.   
  115.   /* 
  116.     Choose a reasonable number of rows,
  117.     allocate space for it and continue until this space
  118.     runs out, then extend the matrix as necessary.
  119.     */
  120.   ct = vector(0,num_cols-1);
  121.   fread(ct,sizeof(*ct),num_cols,fin);
  122.  
  123.   rt = vector(0,num_rows-1);
  124.   m = matrix(0,num_rows-1,0,num_cols-1);
  125.  
  126.   while(fread(&rt[current_row], sizeof(rt[current_row]), 1, fin)==1){ 
  127.     /* We've got another row */
  128.     if(fread(m[current_row],sizeof(*(m[current_row])),num_cols,fin)!=num_cols)
  129.       return(FALSE);      /* Not a True matrix */
  130.  
  131.     current_row++;
  132.     if(current_row>=num_rows){ /* We've got to make a bigger rowsize */
  133.       temp_array = extend_matrix(m,0,num_rows-1,0,num_cols-1,
  134.                  num_rows+ADD_ROWS-1,num_cols-1);
  135.       rt = extend_vector(rt,0,num_rows-1,num_rows+ADD_ROWS-1);
  136.       
  137.       num_rows+= ADD_ROWS;
  138.       m = temp_array;
  139.     }
  140.   }
  141.   /*  finally we force the matrix to be the correct row size */
  142.   /*  bug fixed. procedure called with incorrect 6th argument. jvdwoude@hut.nl */
  143.   temp_array = retract_matrix(m,0,num_rows-1,0,num_cols-1,current_row-1,num_cols-1);
  144.   /* Now save the things that change */
  145.   *ret_matrix = temp_array;
  146.   *row_title = retract_vector(rt, 0, num_rows-1, current_row-1);
  147.   *column_title = ct;
  148.   *nr = current_row;/* Really the total number of rows */
  149.   *nc = num_cols;
  150.   return(TRUE);
  151. }
  152.  
  153. /* This writes a matrix to a stream 
  154.    Note that our ranges are inclusive ranges--and we can specify subsets.
  155.    This behaves similarly to the xrange and yrange operators in gnuplot
  156.    that we all are familiar with.
  157. */
  158. int
  159.   fwrite_matrix(fout,m,nrl,nrh,ncl,nch,row_title,column_title)
  160. register FILE *fout;
  161. register float  GPFAR * GPFAR *m, GPFAR *row_title, GPFAR *column_title;
  162. register int nrl,nrh,ncl,nch;
  163. {
  164.   register int j;
  165.   float length;
  166.   register int col_length;
  167.   register int status;
  168.   float  GPFAR *title = NULL;
  169.  
  170.   length = col_length = nch-ncl+1;
  171.  
  172.   if((status = fwrite((char*)&length,sizeof(float),1,fout))!=1){
  173.     fprintf(stderr,"fwrite 1 returned %d\n",status);
  174.     return(FALSE);
  175.   }
  176.   
  177.   if(!column_title){
  178.     column_title = title = vector(ncl,nch);
  179.     for(j=ncl; j<=nch; j++)
  180.       title[j] = j;
  181.   }
  182.   fwrite((char*)column_title,sizeof(float),col_length,fout);
  183.   if(title){
  184.     free_vector(title,ncl,nch);
  185.     title = NULL;
  186.   }
  187.  
  188.   if(!row_title){
  189.     row_title = title = vector(nrl,nrh);
  190.     for(j=nrl; j<=nrh; j++)
  191.       title[j] = j;
  192.   }
  193.     
  194.   for(j=nrl; j<=nrh; j++){
  195.     fwrite((char*)&row_title[j],sizeof(float),1,fout);
  196.     fwrite((char*)(m[j]+ncl),sizeof(float),col_length,fout);
  197.   }
  198.   if(title)
  199.     free_vector(title,nrl,nrh);
  200.  
  201.   return(TRUE);
  202. }
  203.  
  204. /*===================== Support routines ==============================*/
  205.  
  206. /******************************** VECTOR *******************************
  207.  *       The following routines interact with vectors.
  208.  *
  209.  *   If there is an error we don't really return - int_error breaks us out.
  210.  *
  211.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  212.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  213.  *
  214.  */
  215. float GPFAR *vector(nl,nh)
  216.      register int nl,nh;
  217. {
  218.   register float GPFAR *vec;
  219.  
  220.   if (!(vec = (float GPFAR *)alloc((unsigned long) (nh-nl+1)*sizeof(float), NULL))){
  221.     int_error("not enough memory to create vector",NO_CARET);
  222.     return NULL;/* Not reached */
  223.   }
  224.   return (vec-nl);
  225. }
  226. /* 
  227.  *  Free a vector allocated above
  228.  *
  229.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  230.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  231.  *
  232.  */
  233. void 
  234.   free_vector(vec,nl,nh)
  235. float  GPFAR *vec;
  236. int nl,nh;
  237. {
  238.   free(vec+nl);
  239. }
  240. /************ Routines to modify the length of a vector ****************/  
  241. float  GPFAR *
  242.   extend_vector(vec,old_nl,old_nh,new_nh)
  243. float  GPFAR *vec;
  244. register int old_nl,old_nh,new_nh;
  245. {
  246.   register float  GPFAR *new_v;
  247.   new_v = (float GPFAR *)ralloc((void*)(vec+old_nl),
  248.                        (unsigned long)(new_nh-old_nl+1)*sizeof(float),
  249.                "extend vector");
  250.   return new_v-old_nl;
  251. }
  252.  
  253. float  GPFAR *
  254.   retract_vector(v,old_nl,old_nh,new_nh)
  255. float  GPFAR *v;
  256. register int old_nl,old_nh,new_nh;
  257. {
  258.   register float GPFAR *new_v;
  259.   new_v = (float GPFAR *)ralloc((void*)(v+old_nl),
  260.    (unsigned long)(new_nh-old_nl+1)*sizeof(float), "retract vector");
  261.   return new_v-old_nl;
  262. }
  263. /***************************** MATRIX ************************
  264.  *
  265.  *       The following routines work with matricies
  266.  *
  267.  *      I always get confused with this, so here I write it down:
  268.  *               for nrl<= nri <=nrh and
  269.  *               for ncl<= ncj <=nch
  270.  *  
  271.  *   This matrix is accessed as:
  272.  *   
  273.  *     matrix[nri][ncj];
  274.  *     where nri is the offset to the pointer to a vector where the
  275.  *     ncjth element lies.
  276.  * 
  277.  *   If there is an error we don't really return - int_error breaks us out.
  278.  *
  279.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  280.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  281.  *
  282.  */
  283. float 
  284.    GPFAR * GPFAR *matrix(nrl,nrh,ncl,nch)
  285. register int nrl,nrh,ncl,nch;
  286. {
  287.   register int i;
  288.   register float GPFAR * GPFAR *m;
  289.  
  290.   m = (float GPFAR * GPFAR *)alloc((unsigned long)(nrh-nrl+1)*sizeof(float GPFAR *), "matrix");
  291.   m -= nrl;
  292.  
  293.   for (i=nrl; i<=nrh; i++)
  294.     {
  295.       if(!(m[i] = (float GPFAR *) alloc((unsigned long)(nch-ncl+1)*sizeof(float), NULL))){
  296.     free_matrix(m,nrl,i-1,ncl,nch);
  297.     int_error("not enough memory to create matrix",NO_CARET);
  298.     return NULL;
  299.       }
  300.       m[i] -= ncl;
  301.     }
  302.   return m;
  303. }
  304. /* 
  305.  * Free a matrix allocated above
  306.  *
  307.  *
  308.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  309.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  310.  *
  311.  */
  312. void 
  313.   free_matrix(m,nrl,nrh,ncl,nch)
  314. float  GPFAR * GPFAR *m;
  315. unsigned nrl,nrh,ncl,nch;
  316. {
  317.   register int i;
  318.  
  319.   for (i=nrl; i<=nrh; i++) 
  320.     free((char GPFAR *) (m[i]+ncl));
  321.   free((char GPFAR *) (m+nrl));
  322. }
  323. /*
  324.   This routine takes a sub matrix and extends the number of rows and 
  325.   columns for a new matrix
  326. */
  327. float GPFAR * GPFAR *extend_matrix(a,nrl,nrh,ncl,nch,srh,sch)
  328.      register float  GPFAR * GPFAR *a;
  329.      register int nrl,nrh,ncl,nch;
  330.      register int srh,sch;
  331. {
  332.   register int i;
  333.   register float GPFAR * GPFAR *m;
  334.  
  335.   m = (float GPFAR * GPFAR *)ralloc((void*)(a+nrl),(unsigned long)(srh-nrl+1)*sizeof(float GPFAR *), "extend matrix");
  336.  
  337.   m -= nrl;
  338.  
  339.   if(sch != nch){
  340.     for(i=nrl; i<=nrh; i++)
  341.       {/* Copy and extend rows */
  342.     if(!(m[i] = extend_vector(m[i],ncl,nch,sch))){
  343.       free_matrix(m,nrl,nrh,ncl,sch);
  344.       int_error("not enough memory to extend matrix",NO_CARET);
  345.       return NULL;
  346.     }
  347.       }
  348.   }
  349.   for(i=nrh+1; i<=srh; i++)
  350.     {
  351.       if(!(m[i] = (float GPFAR *) alloc((unsigned long) (nch-ncl+1)*sizeof(float), NULL))){
  352.     free_matrix(m,nrl,i-1,nrl,sch);
  353.     int_error("not enough memory to extend matrix",NO_CARET);
  354.     return NULL;
  355.       }
  356.       m[i] -= ncl;
  357.     }
  358.   return m;
  359. }
  360. /*
  361.   this routine carves a large matrix down to size
  362. */
  363. float GPFAR * GPFAR *retract_matrix(a,nrl,nrh,ncl,nch,srh,sch)
  364.      register float  GPFAR * GPFAR *a;
  365.      register int nrl,nrh,ncl,nch;
  366.      register int srh,sch;
  367. {
  368.   register int i;
  369.   register float  GPFAR * GPFAR *m;
  370.  
  371.   for(i=srh+1; i<=nrh; i++) {
  372.     free_vector(a[i],ncl,nch);
  373.   }
  374.  
  375.   m = (float GPFAR * GPFAR *)ralloc((void*)(a+nrl), (unsigned long)(srh-nrl+1)*sizeof(float GPFAR *), "retract matrix");
  376.  
  377.   m -= nrl;
  378.  
  379.   if(sch != nch){
  380.     for(i=nrl; i<=srh; i++)       
  381.     if(!(m[i] = retract_vector(m[i],ncl,nch,sch))){ {/* Shrink rows */
  382.       free_matrix(m,nrl,srh,ncl,sch);
  383.       int_error("not enough memory to retract matrix",NO_CARET);
  384.       return NULL;
  385.     }
  386.       }
  387.   }
  388.  
  389.   return m;
  390. }
  391.  
  392. float 
  393.    GPFAR * GPFAR *convert_matrix(a,nrl,nrh,ncl,nch)
  394. float GPFAR *a;
  395. register int nrl,nrh,ncl,nch;
  396.  
  397. /* allocate a float matrix m[nrl...nrh][ncl...nch] that points to the
  398. matrix declared in the standard C manner as a[nrow][ncol], where 
  399. nrow=nrh-nrl+1, ncol=nch-ncl+1.  The routine should be called with
  400. the address &a[0][0] as the first argument.  This routine does
  401. not free the memory used by the original array a but merely assigns
  402. pointers to the rows. */
  403.  
  404. {
  405.   register int i,j,ncol,nrow;
  406.   register float GPFAR * GPFAR *m;
  407.  
  408.   nrow=nrh-nrl+1;
  409.   ncol=nch-ncl+1;
  410.   m = (float GPFAR * GPFAR *)alloc((unsigned long)(nrh-nrl+1)*sizeof(float GPFAR *), "convert_matrix");
  411.   m -= nrl;
  412.  
  413.   m[nrl]=a-ncl;
  414.   for(i=1,j=nrl+1;i<=nrow-1;i++,j++) m[j]=m[j-1]+ncol;
  415.   return m;
  416. }
  417.  
  418. void free_convert_matrix(b,nrl,nrh,ncl,nch)
  419. float GPFAR* GPFAR *b;
  420. register int nrl,nrh,ncl,nch;
  421. {
  422.     free((char*) (b+nrl));
  423. }
  424.